package com.app.business.calculate;

import com.app.business.en.HouseType;
import com.app.business.model.*;
import com.app.business.service.*;
import com.app.business.utils.AreaAndPriceUtils;
import com.app.business.utils.CalculateDate;
import com.app.system.permission.service.DataDictService;
import com.app.system.utils.ApplicationContextProvider;
import com.app.system.utils.CollectionUtils;
import com.app.system.utils.dataType.BigDecimalUtils;
import com.app.system.utils.dataType.IntegerUtils;
import com.google.common.collect.Maps;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 计算方法
 * Created by ZYK on 2019/2/28.
 */
public class CalculateUtils {

    private static ContractService contractService;
    private static OverAreaPriceNewService overAreaPriceNewService;
    private static OverAreaOneFloorSyPriceService overAreaOneFloorSyPriceService;
    private static OverAreaTwoFloorSyPriceService overAreaTwoFloorSyPriceService;
    private static OverAreaXzlPriceService overAreaXzlPriceService;
    private static OverAreaScPriceService overAreaScPriceService;
    private static SyKgInfoService syKgInfoService;
    private static HouseService houseService;
    private static StorageRoomService storageRoomService;
    private static CarLotService carLotService;
    private static DataDictService dataDictService;
    private static ShopHouseService shopHouseService;
    private static AdjustAreaService adjustAreaService;

    /**
     * 自动计算
     * 接受一个对象，对此对象的方案补助款分别计算
     *
     * @param contractId
     * @throws IllegalAccessException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
    public synchronized static void main(Integer contractId) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
        contractService = (ContractService) applicationContext.getBean(ContractService.class);
        houseService = (HouseService) applicationContext.getBean(HouseService.class);
        storageRoomService = (StorageRoomService) applicationContext.getBean(StorageRoomService.class);
        carLotService = (CarLotService) applicationContext.getBean(CarLotService.class);
        dataDictService = (DataDictService) applicationContext.getBean(DataDictService.class);
        overAreaPriceNewService = (OverAreaPriceNewService) applicationContext.getBean(OverAreaPriceNewService.class);
        overAreaOneFloorSyPriceService = (OverAreaOneFloorSyPriceService) applicationContext.getBean(OverAreaOneFloorSyPriceService.class);
        overAreaTwoFloorSyPriceService = (OverAreaTwoFloorSyPriceService) applicationContext.getBean(OverAreaTwoFloorSyPriceService.class);
        overAreaXzlPriceService = (OverAreaXzlPriceService) applicationContext.getBean(OverAreaXzlPriceService.class);
        overAreaScPriceService = (OverAreaScPriceService) applicationContext.getBean(OverAreaScPriceService.class);
        syKgInfoService = (SyKgInfoService) applicationContext.getBean(SyKgInfoService.class);
        shopHouseService = (ShopHouseService) applicationContext.getBean(ShopHouseService.class);
        adjustAreaService = (AdjustAreaService) applicationContext.getBean(AdjustAreaService.class);
        Contract contract = contractService.findOne(contractId);
        if (contract == null || contract.getZsProject() == null) {
            return;
        }
        //计算合并面积
        contract = calAdjustArea(contract);
        //以下计算：正数代表：被征收人应领取的金额；负数代表：被征收人应补缴的金额
        contract = calArea(contract);
        System.out.println("房源、储物间面积计算完成！");
        contract = calKkgArea(contract);
        System.out.println("可扩改建筑面积、金额计算完成！");
        contract = calSyArea(contract);
        System.out.println("未结算剩余面积已计算！");

        if (contract.getZsProject().getProjectName().contains("第二批次")) {
            contract = calSyMoney(contract);
            System.out.println("商业购房款计算完成！");
        } else {
            contract = calMoney(contract);
            System.out.println("房源、储物间购房款计算完成！");
        }
        if (contract.getIsJiSuan() != null && contract.getIsJiSuan() != 1) {
            contract = calSyArea(contract);
            System.out.println("未结算剩余面积已计算！");
        }
        contract = calCarLotMoney(contract);
        System.out.println("车位计算完成！");
        contract = calBzMoney(contract);
        System.out.println("过渡费计算完成！");
        contract = calWxMoney(contract);
        System.out.println("专项维修基金计算完成！");
        contract = calOtherMoney(contract);
        System.out.println("其他费用计算完成！");
        contract = calTaxMoney(contract);
        System.out.println("契税、印花税费用计算完成！");
        contract = contractCodeZzAddCal(contract);
        System.out.println("子编号计算完成！");
        contract = calQjInfo(contract);
        System.out.println("区间面积计算！");
        contractService.save(contract);
        System.out.println("************************计算完成！************************");
    }

    /**
     * 计算房源的面积、数量
     *
     * @param contract
     * @return
     */
    private static Contract calArea(Contract contract) {
        //选择的普通型房源数量、选择的小户型房源数量、房源总数
        Integer normalHouseNum = 0, smallHouseNum = 0, fsHouseNum = 0, houseNum = 0;
        //选择的普通型房源面积、选择的小户型房源面积、房源总面积
        BigDecimal normalHouseArea = BigDecimal.ZERO, smallHouseArea = BigDecimal.ZERO, fsHouseArea = BigDecimal.ZERO, chooseHouseAreaTotal = BigDecimal.ZERO, chooseHouseAreaTotalForDisplace = BigDecimal.ZERO;
        //需要进行申购金额,面积
        BigDecimal buyHouseArea = BigDecimal.ZERO, buyHouseAreaMoney = BigDecimal.ZERO;
        //选房期房、现房面积分别多少
        BigDecimal chooseHouseQiFangAreaTotal = BigDecimal.ZERO, chooseHouseXianFangAreaTotal = BigDecimal.ZERO;
        List<House> houseList = houseService.getHouseListByContractId(contract.getId());

        Boolean isDisplace = false;
        if (CollectionUtils.isNotEmpty(houseList)) {
            for (House house : houseList) {
                if (house.getHouseType() == null) {
                    continue;
                }
                if (house.getIsDisplace() != null && house.getIsDisplace() == 2) {
                    isDisplace = true;
                }
                if (house.getIsDisplace() != null && house.getIsDisplace() == 2) {
                    chooseHouseAreaTotalForDisplace = BigDecimalUtils.getSum(chooseHouseAreaTotalForDisplace, house.getBuildAreaForDisplace());
                    buyHouseArea = BigDecimalUtils.getSum(buyHouseArea, house.getBuyArea());
                    buyHouseAreaMoney = BigDecimalUtils.getSum(buyHouseAreaMoney, house.getBuyAreaMoney());
                } else {
                    chooseHouseAreaTotalForDisplace = BigDecimalUtils.getSum(chooseHouseAreaTotalForDisplace, house.getBuildArea());
                }
                //普通型
                if (house.getHouseType().equals(HouseType.NORMAL.getIndex())) {
                    normalHouseNum++;
                    normalHouseArea = BigDecimalUtils.getSum(normalHouseArea, house.getBuildArea());
                } else if (house.getHouseType().equals(HouseType.SMALL.getIndex())) {   //小户型（单身公寓）
                    smallHouseNum++;
                    smallHouseArea = BigDecimalUtils.getSum(smallHouseArea, house.getBuildArea());
                } else if (house.getHouseType().equals(HouseType.FS.getIndex())) {   //复式
                    fsHouseNum++;
                    fsHouseArea = BigDecimalUtils.getSum(fsHouseArea, house.getBuildArea());
                }
            }
            if (isDisplace) {
                contract.setIsDisplace(2);
            } else {
                contract.setIsDisplace(1);
            }
            houseNum = IntegerUtils.getSum(normalHouseNum, smallHouseNum, fsHouseNum);   //房源总数量
            chooseHouseAreaTotal = BigDecimalUtils.getSum(normalHouseArea, smallHouseArea, fsHouseArea);   //房源总面积
            if (contract.getIsDisplace() != null && contract.getIsDisplace() == 1) {
                chooseHouseAreaTotalForDisplace = chooseHouseAreaTotal;
            }
        }
        //获取已选现房房源
        List<House> houseNature1List = houseService.getHouseListByContractIdAndHouseNature1(contract.getId());
        //获取已选期房房源
        List<House> houseNature2List = houseService.getHouseListByContractIdAndHouseNature2(contract.getId());

        BigDecimal houseNature1Area = BigDecimal.ZERO;
        BigDecimal houseNature2Area = BigDecimal.ZERO;
        BigDecimal houseNature2ZhArea = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(houseNature1List)) {
            for (House house : houseNature1List) {
                houseNature1Area = BigDecimalUtils.getSum(houseNature1Area, house.getBuildArea());
            }
        }
        if (CollectionUtils.isNotEmpty(houseNature2List)) {
            for (House house : houseNature2List) {
                houseNature2Area = BigDecimalUtils.getSum(houseNature2Area, house.getBuildArea());
                houseNature2ZhArea = BigDecimalUtils.getSum(houseNature2ZhArea, house.getDisplaceAreaForAzArea());
            }
        }

        //店铺情况面积 2024年5月5日 店面用于置换即店面总价值/6500元
        List<ShopHouse> shopHouseList = shopHouseService.getShopHouseListByContractId(contract.getId());

        Integer shopHouseNum = 0;  //店铺数量
        BigDecimal shopHouseArea = BigDecimal.ZERO; //店铺面积
        BigDecimal dmResultArea = BigDecimal.ZERO;//店面面积（抵扣后最终店面面积：用于计算）
        if (CollectionUtils.isNotEmpty(shopHouseList)) {
            for (ShopHouse shopHouse : shopHouseList) {
                shopHouseNum++;
                shopHouseArea = BigDecimalUtils.getSum(shopHouseArea,shopHouse.getBuildArea());
                dmResultArea = BigDecimalUtils.getSum(dmResultArea,shopHouse.getSxZhArea());
            }
        }
        contract.setShopHouseNum(shopHouseNum);
        contract.setShopHouseArea(shopHouseArea);
        contract.setDmResultArea(dmResultArea);//所需置换店面的面积

        //车位情况面积 2024年7月22日  车位可以用面积置换
        List<CarLot> carLotList = carLotService.getCarLotListByContractId(contract.getId());
        BigDecimal carLotTotalZhArea = BigDecimal.ZERO;//置换车位最终所需金额
        if (CollectionUtils.isNotEmpty(carLotList)) {
            for (CarLot carLot : carLotList) {
                if (carLot.getSfHg() == 2) {//面积换购时仅需要计算面积
                    carLotTotalZhArea = BigDecimalUtils.getSum(carLotTotalZhArea,carLotService.carLotZhArea(carLot));
                }
            }
        }
        contract.setNormalHouseNum(normalHouseNum);
        contract.setSmallHouseNum(smallHouseNum);
        contract.setNormalHouseArea(normalHouseArea);
        contract.setSmallHouseArea(smallHouseArea);
        contract.setHouseNum(houseNum);
        contract.setChooseHouseAreaTotal(chooseHouseAreaTotal);
        contract.setChooseHouseAreaTotalForDisplace(chooseHouseAreaTotalForDisplace);
        contract.setChooseHouseXianFangAreaTotal(houseNature1Area);
        contract.setChooseHouseQiFangAreaTotal(houseNature2Area);
        contract.setChooseHouseQiFangZhAreaTotal(houseNature2ZhArea);
        contract.setBuyHouseArea(buyHouseArea);
        contract.setBuyHouseAreaMoney(buyHouseAreaMoney.negate());

        List<StorageRoom> storageRoomList = storageRoomService.getStorageRoomListByContractId(contract.getId());
        Integer storageRoomNum = 0;  //储物间数量
        //储物间面积
        BigDecimal storageRoomArea = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(storageRoomList)) {
            for (StorageRoom storageRoom : storageRoomList) {
                storageRoomNum++;
                storageRoomArea = BigDecimalUtils.getSum(storageRoomArea, storageRoom.getBuildArea());
            }
        }
        contract.setStorageRoomNum(storageRoomNum);
        contract.setStorageRoomArea(storageRoomArea);



        //住宅面积(不含储藏间)（抵扣后）、储藏间面积（抵扣后）
        BigDecimal zzResultArea = BigDecimal.ZERO, ccjResultArea = BigDecimal.ZERO;
        //若选房面积未超出执行以下计算，否则：可直接得出扩购面积、储物间面积
        if (contract.getIsDisplace() != null && contract.getIsDisplace() == 2) {
            chooseHouseAreaTotal = chooseHouseAreaTotalForDisplace;
        }
        if (contract.getLimitHouseAreaTotal().compareTo(chooseHouseAreaTotal) > 0) {
            //得到选房后还剩余的面积
            BigDecimal centerArea1 = BigDecimalUtils.getBigAndBigSub(contract.getLimitHouseAreaTotal(), chooseHouseAreaTotal);
            //得到所选储物间面积换算成产权面积后的面积
            BigDecimal centerArea2 = BigDecimal.ZERO;
            if (contract.getAzType().contains("商业")) {
                centerArea2 = BigDecimalUtils.getBigAndBigDiv(storageRoomArea, new BigDecimal("1.9"), 2);
            } else {
                centerArea2 = BigDecimalUtils.getBigAndBigDiv(storageRoomArea, contract.getParameter().getCwjBl(), 2);
            }
            if (contract.getBuyStorageRoomType() != 2) {
                if (centerArea1.compareTo(centerArea2) >= 0) {
                    //如果剩余的面积 > 所选储物间面积换算成产权面积后的面积，那么不存在扩购，储物间面积也为0，得出产权减少的面积（负的）
                    zzResultArea = BigDecimalUtils.getBigAndBigSub(centerArea2, centerArea1);
                } else {
                    //否则，扩购面积为0，产权超出的面积*1.5即为，储物间换算后的面积
                    ccjResultArea = BigDecimalUtils.getBigAndBigMul(BigDecimalUtils.getBigAndBigSub(centerArea2, centerArea1), contract.getParameter().getCwjBl()).setScale(2, BigDecimal.ROUND_HALF_UP);
                }
            } else {
                zzResultArea = BigDecimalUtils.getBigAndBigSub(chooseHouseAreaTotal, contract.getLimitHouseAreaTotal());
                ccjResultArea = storageRoomArea;
            }
        } else {
            zzResultArea = BigDecimalUtils.getBigAndBigSub(chooseHouseAreaTotal, contract.getLimitHouseAreaTotal());
            ccjResultArea = storageRoomArea;
        }
        zzResultArea = BigDecimalUtils.getSum(zzResultArea,carLotTotalZhArea,dmResultArea);
        contract.setZzResultArea(zzResultArea);


        if (contract.getIsJiSuan() != null) {
            if (contract.getIsJiSuan() == 2 || contract.getIsJiSuan() == 3) {
                contract.setZzResultArea(BigDecimal.ZERO);
            }
        }
        contract.setCcjResultArea(ccjResultArea);

        //商业商场面积计算 剩余面积
        BigDecimal oneFloorSyAzShopArea = BigDecimal.ZERO,twoFloorSyAzShopArea = BigDecimal.ZERO,syScAzShopArea = BigDecimal.ZERO,syScXzlShopArea = BigDecimal.ZERO;
        //商业商场面积计算 负数扩购，正数回购
        BigDecimal syDmAzSyArea = BigDecimal.ZERO,syTwoFloorAzSyArea = BigDecimal.ZERO,syScAzSyArea = BigDecimal.ZERO,syXzlAzSyArea = BigDecimal.ZERO;
        //商业安置沿街名称
        StringBuffer oneFloorSyName = new StringBuffer("");
        StringBuffer twoFloorSyName = new StringBuffer("");
        StringBuffer syScName = new StringBuffer("");
        StringBuffer syXzlName = new StringBuffer("");
        List<ShopHouse> shopHouseList1 = shopHouseService.getShopHouseListByContractId(contract.getId());
        if (CollectionUtils.isNotEmpty(shopHouseList1)) {
            for (ShopHouse shopHouse : shopHouseList1) {
                if (shopHouse.getHouseYc().equals("店面")){
                    if (!oneFloorSyName.toString().contains(shopHouse.getYjName()) && shopHouse.getOneFloorArea().compareTo(BigDecimal.ZERO)>0){
                        oneFloorSyName.append(shopHouse.getYjName() + " ");
                    }
                    if (!twoFloorSyName.toString().contains(shopHouse.getYjName()) && shopHouse.getTwoFloorArea().compareTo(BigDecimal.ZERO)>0){
                        twoFloorSyName.append(shopHouse.getYjName() + " ");
                    }
                    oneFloorSyAzShopArea = BigDecimalUtils.getSum(oneFloorSyAzShopArea,shopHouse.getOneFloorArea());
                    twoFloorSyAzShopArea = BigDecimalUtils.getSum(twoFloorSyAzShopArea,shopHouse.getTwoFloorArea());
                } else if (shopHouse.getHouseYc().equals("商业商场")) {
                    if (!syScName.toString().contains(shopHouse.getYjName())){
                        syScName.append(shopHouse.getYjName() + " ");
                    }
                    syScAzShopArea = BigDecimalUtils.getSum(syScAzShopArea,shopHouse.getBuildArea());
                } else if (shopHouse.getHouseYc().equals("写字楼")) {
                    if (!syXzlName.toString().contains(shopHouse.getYjName())){
                        syXzlName.append(shopHouse.getYjName() + " ");
                    }
                    syScXzlShopArea = BigDecimalUtils.getSum(syScXzlShopArea,shopHouse.getBuildArea());
                }
            }
        }
        //商业已安置
        contract.setOneFloorSyAzShopArea(oneFloorSyAzShopArea);
        contract.setTwoFloorSyAzShopArea(twoFloorSyAzShopArea);
        contract.setSyScAzShopArea(syScAzShopArea);
        contract.setSyXzlShopArea(syScXzlShopArea);
        //商业安置后剩余面积 负数需扩购  正数需回购
        syDmAzSyArea = BigDecimalUtils.getBigAndBigSub(oneFloorSyAzShopArea,contract.getOneFlorSyAreaTotal());//一层商业 及 住改商剩余
        syTwoFloorAzSyArea = BigDecimalUtils.getBigAndBigSub(twoFloorSyAzShopArea,contract.getSyTwoFloorAzArea());//二层商业
        syScAzSyArea = BigDecimalUtils.getBigAndBigSub(syScAzShopArea,contract.getSyScAzArea());//商业商场
        syXzlAzSyArea = BigDecimalUtils.getBigAndBigSub(syScXzlShopArea,contract.getSyXzlAzArea());//商业写字楼

        contract.setSyDmAzSyArea(syDmAzSyArea);
        contract.setSyTwoFloorAzSyArea(syTwoFloorAzSyArea);
        contract.setSyScAzSyArea(syScAzSyArea);
        contract.setSyXzlAzSyArea(syXzlAzSyArea);
        //商业沿街名称
        contract.setOneFloorSyName(oneFloorSyName.toString());
        contract.setTwoFloorSyName(twoFloorSyName.toString());
        contract.setSyScName(syScName.toString());
        contract.setSyXzlName(syXzlName.toString());

        return contract;
    }

    /**
     * 计算购房款
     *
     * @param contract
     * @return
     */
    private static Contract calMoney(Contract contract) {
        //房源购房款、储物间购房款
        BigDecimal houseMoney = BigDecimal.ZERO, storageRoomMoney = BigDecimal.ZERO;

        //判断是否只有单扩购或者单回购一种情况
        if (contract.getZzResultAreaStatus() != null && contract.getZzResultAreaStatus() == 1) {
            //如果使用之前的方案，则只使用扩购
            if (contract.getParameter().getId() < 0) {
                if (contract.getZzResultArea().compareTo(BigDecimal.ZERO) <= 0) {
                    //选房不足，购房款为正数（被征收人应领取金额），每平米3000元（每个项目可能不同）补偿
                    houseMoney = BigDecimalUtils.getBigAndBigMul(contract.getZzResultArea(), contract.getParameter().getXfbcPrice()).setScale(0, BigDecimal.ROUND_HALF_UP).negate();
                    if (contract.getIsJiSuan() != null && contract.getIsJiSuan() != 1) {
                        houseMoney = new BigDecimal("0");
                    }
                } else {
                    Map<String, Map> resultMap = overAreaPriceNewService.getOverHouseMoneyMapForMore(contract);
                    houseMoney = calHouseMoneyForQuJian(resultMap);
                }
            } else {
                //否则
                //如果扩购，只有扩购区间
                if (contract.getZzResultArea().compareTo(BigDecimal.ZERO) >= 0) {
                    Map<String, Map> resultMap = overAreaPriceNewService.getOverHouseMoneyMapForMore(contract);
                    houseMoney = calHouseMoneyForQuJian(resultMap);
                } else {
                    //否则回购
                    //回购如果回购单价不为区间的话,为固定值，则扩购回购都为空
                    if (contract.getParameter().getXfbcPrice() != null && contract.getParameter().getXfbcPrice().compareTo(BigDecimal.ZERO) > 0) {
                        //否则根据3855进行补偿
                        //选房不足，购房款为正数（被征收人应领取金额），每平米3000元（每个项目可能不同）补偿
                        houseMoney = BigDecimalUtils.getBigAndBigMul(contract.getZzResultArea(), contract.getParameter().getXfbcPrice()).setScale(0, BigDecimal.ROUND_HALF_UP).negate();
                        if (contract.getIsJiSuan() != null && contract.getIsJiSuan() != 1) {
                            houseMoney = new BigDecimal("0");
                        }
                    } else {
                        Map<String, Map> resultMap = overAreaPriceNewService.getOverHouseMoneyMapForLess(contract);
                        houseMoney = calHouseMoneyForQuJian(resultMap);
                    }
                }

            }
            //可能存在先回购，再扩购的情况  使用特殊区间计算
        } else if (contract.getZzResultAreaStatus() != null && contract.getZzResultAreaStatus() == 2) {
            Map<String, Map> resultMap = overAreaPriceNewService.getOverHouseMoneySpecialMap(contract);
            houseMoney = calHouseMoneyForQuJian(resultMap);
        }


        if (contract.getIsJiSuan() != null && contract.getIsJiSuan() != 1) {
            houseMoney = new BigDecimal("0");
        }
        //储物间购房款 = 储物间面积(抵扣后) * 储物间申购单价 （为负数：被征收人应缴纳金额）
        storageRoomMoney = BigDecimalUtils.getBigAndBigMul(contract.getCcjResultArea(), contract.getParameter().getCwjPrice()).setScale(0, BigDecimal.ROUND_HALF_UP).negate();
        contract.setStorageRoomMoney(storageRoomMoney);
        houseMoney=BigDecimalUtils.getSum(houseMoney,contract.getBuyHouseAreaMoney());
        contract.setHouseMoney(houseMoney);
        return contract;
    }

    /**
     * 一层商业款计算
     * @param contract
     * @return
     */
    private static Contract calOneFloorSyMoney(Contract contract) {
        //一层商业购房款
        BigDecimal syDmMoney = BigDecimal.ZERO;
        //如果扩购，只有扩购区间
        if (contract.getSyDmAzSyArea().compareTo(BigDecimal.ZERO) >= 0) {
            Map<String, Map> resultMap = overAreaOneFloorSyPriceService.getOverHouseMoneyMapForMore(contract);
            syDmMoney = calHouseMoneyForQuJian(resultMap);
        } else {
            //否则回购
            //回购如果回购单价不为区间的话,为固定值，则扩购回购都为空
            if (contract.getParameter().getSyDmAzSyAzBzPrice() != null && contract.getParameter().getSyDmAzSyAzBzPrice().compareTo(BigDecimal.ZERO) > 0) {
                //否则根据3855进行补偿
                //选房不足，购房款为正数（被征收人应领取金额），每平米3000元（每个项目可能不同）补偿
                syDmMoney = BigDecimalUtils.getBigAndBigMul(contract.getSyDmAzSyArea(), contract.getParameter().getSyDmAzSyAzBzPrice()).setScale(0, BigDecimal.ROUND_HALF_UP).negate();
                if (contract.getIsJiSuan() != null && contract.getIsJiSuan() != 1) {
                    syDmMoney = new BigDecimal("0");
                }
            }
        }
        syDmMoney=BigDecimalUtils.getSum(syDmMoney,BigDecimal.ZERO);
        contract.setSyDmMoney(syDmMoney);
        return contract;
    }
    /**
     * 二层商业款计算
     * @param contract
     * @return
     */
    private static Contract calTwoFloorSyMoney(Contract contract) {
        //一层商业购房款
        BigDecimal syTwoFloorMoney = BigDecimal.ZERO;
        //如果扩购，只有扩购区间
        if (contract.getSyTwoFloorAzSyArea().compareTo(BigDecimal.ZERO) >= 0) {
            Map<String, Map> resultMap = overAreaTwoFloorSyPriceService.getOverHouseMoneyMapForMore(contract);
            syTwoFloorMoney = calHouseMoneyForQuJian(resultMap);
        } else {
            //否则回购
            //回购如果回购单价不为区间的话,为固定值，则扩购回购都为空
            if (contract.getParameter().getSyTwoFloorAzSyAzBzPrice() != null && contract.getParameter().getSyTwoFloorAzSyAzBzPrice().compareTo(BigDecimal.ZERO) > 0) {
                //否则根据3855进行补偿
                //选房不足，购房款为正数（被征收人应领取金额），每平米3000元（每个项目可能不同）补偿
                syTwoFloorMoney = BigDecimalUtils.getBigAndBigMul(contract.getSyTwoFloorAzSyArea(), contract.getParameter().getSyTwoFloorAzSyAzBzPrice()).setScale(0, BigDecimal.ROUND_HALF_UP).negate();
                if (contract.getIsJiSuan() != null && contract.getIsJiSuan() != 1) {
                    syTwoFloorMoney = new BigDecimal("0");
                }
            }
        }
        syTwoFloorMoney=BigDecimalUtils.getSum(syTwoFloorMoney,BigDecimal.ZERO);
        contract.setSyTwoFloorMoney(syTwoFloorMoney);
        return contract;
    }

    /**
     * 商业商场款计算
     * @param contract
     * @return
     */
    private static Contract calScMoney(Contract contract) {
        //一层商业购房款
        BigDecimal syScMoney = BigDecimal.ZERO;
        //如果扩购，只有扩购区间
        if (contract.getSyScAzSyArea().compareTo(BigDecimal.ZERO) >= 0) {
            Map<String, Map> resultMap = overAreaScPriceService.getOverHouseMoneyMapForMore(contract);
            syScMoney = calHouseMoneyForQuJian(resultMap);
        } else {
            //否则回购
            //回购如果回购单价不为区间的话,为固定值，则扩购回购都为空
            if (contract.getParameter().getSyScAzSyAzBzPrice() != null && contract.getParameter().getSyScAzSyAzBzPrice().compareTo(BigDecimal.ZERO) > 0) {
                //否则根据3855进行补偿
                //选房不足，购房款为正数（被征收人应领取金额），每平米3000元（每个项目可能不同）补偿
                syScMoney = BigDecimalUtils.getBigAndBigMul(contract.getSyScAzSyArea(), contract.getParameter().getSyScAzSyAzBzPrice()).setScale(0, BigDecimal.ROUND_HALF_UP).negate();
                if (contract.getIsJiSuan() != null && contract.getIsJiSuan() != 1) {
                    syScMoney = new BigDecimal("0");
                }
            }
        }
        syScMoney=BigDecimalUtils.getSum(syScMoney,BigDecimal.ZERO);
        contract.setSyScMoney(syScMoney);
        return contract;
    }

    /**
     * 写字楼计算
     * @param contract
     * @return
     */
    private static Contract calXzlMoney(Contract contract) {
        //一层商业购房款
        BigDecimal syXzlMoney = BigDecimal.ZERO;
        //如果扩购，只有扩购区间
        if (contract.getSyXzlAzSyArea().compareTo(BigDecimal.ZERO) >= 0) {
            Map<String, Map> resultMap = overAreaScPriceService.getOverHouseMoneyMapForMore(contract);
            syXzlMoney = calHouseMoneyForQuJian(resultMap);
        } else {
            //否则回购
            //回购如果回购单价不为区间的话,为固定值，则扩购回购都为空
            if (contract.getParameter().getSyXzlAzSyAzBzPrice() != null && contract.getParameter().getSyXzlAzSyAzBzPrice().compareTo(BigDecimal.ZERO) > 0) {
                //否则根据3855进行补偿
                //选房不足，购房款为正数（被征收人应领取金额），每平米3000元（每个项目可能不同）补偿
                syXzlMoney = BigDecimalUtils.getBigAndBigMul(contract.getSyXzlAzSyArea(), contract.getParameter().getSyXzlAzSyAzBzPrice()).setScale(0, BigDecimal.ROUND_HALF_UP).negate();
                if (contract.getIsJiSuan() != null && contract.getIsJiSuan() != 1) {
                    syXzlMoney = new BigDecimal("0");
                }
            }
        }
        syXzlMoney=BigDecimalUtils.getSum(syXzlMoney,BigDecimal.ZERO);
        contract.setSyXzlMoney(syXzlMoney);
        return contract;
    }

    /**
     * 商业购房款计算
     * @param contract
     * @return
     */
    private static Contract calSyMoney(Contract contract) {
        //商业购房款
        BigDecimal syMoney = BigDecimal.ZERO;
        List<SyKgInfo> syKgInfoList = new LinkedList<>();
        if (contract.getAzType().contains("商业") && contract.getParameter() != null) {
            syKgInfoList = syKgInfoService.getSyKgInfoListByParameterId(contract.getParameter().getId());
        }
        if (CollectionUtils.isNotEmpty(syKgInfoList)) {
            for (SyKgInfo syKgInfo : syKgInfoList) {
                syMoney = BigDecimalUtils.getSum(syMoney,syKgInfo.getMoney());
            }
        }
        contract.setHouseMoney(syMoney);
        return contract;
    }

    //计算不同情况累计，公用
    private static BigDecimal calHouseMoneyForQuJian(Map<String, Map> resultMap) {
        BigDecimal houseMoney = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(resultMap)) {
            Map itemMap = Maps.newHashMap();
            for (String str : resultMap.keySet()) {
                itemMap = null;
                itemMap = resultMap.get(str) == null ? Maps.newHashMap() : resultMap.get(str);
                //循环取出每个面积段的购房款，如果为空或0，则为0，累加起来为总的需要缴的购房款
                BigDecimal money = (itemMap.get("money") == null || itemMap.get("money").toString().equals("")) ? BigDecimal.ZERO : new BigDecimal(itemMap.get("money").toString());
                houseMoney = BigDecimalUtils.getSum(houseMoney, money);
            }
        }
        return houseMoney;
    }

    /**
     * 区间面积计算
     * @param contract
     * @return
     */
    public static Contract calQjInfo(Contract contract) {
        Map<String, Map> resultMap = new HashMap<>();
        if (contract.getZzResultArea().compareTo(BigDecimal.ZERO) <= 0) {
            resultMap = new HashMap<>();
        } else {
            resultMap = overAreaPriceNewService.getOverHouseMoneyMapForMore(contract);
        }
        if (CollectionUtils.isNotEmpty(resultMap)) {
            Map itemMap = Maps.newHashMap();
            for (String str : resultMap.keySet()) {
                itemMap = null;
                itemMap = resultMap.get(str) == null ? Maps.newHashMap() : resultMap.get(str);

                /*存储区间相关面积及金额*/
                if (CollectionUtils.isNotEmpty(itemMap)) {
                    BigDecimal area = BigDecimal.ZERO,price = BigDecimal.ZERO,qjMoney = BigDecimal.ZERO;
                    if (itemMap.get("area") != null) {
                        area = BigDecimalUtils.stringToBigDecimal(itemMap.get("area").toString());
                    }
                    if (itemMap.get("price") != null) {
                        price = BigDecimalUtils.stringToBigDecimal(itemMap.get("price").toString());
                    }
                    if (itemMap.get("money") != null) {
                        qjMoney = BigDecimalUtils.stringToBigDecimal(itemMap.get("money").toString());
                    }
                    if (price.compareTo(new BigDecimal("9100")) == 0) {
                        contract.setTwoQjArea(area);
                        contract.setTwoQjMoney(qjMoney);
                    } else if (price.compareTo(new BigDecimal("3800")) == 0) {
                        contract.setOneQjArea(area);
                        contract.setOneQjMoney(qjMoney);
                    }
                }
            }
        }
        return contract;
    }

    public static void calQjInfoCal(Contract contract) {
        Map<String, Map> resultMap = new HashMap<>();
        if (contract.getZzResultArea() == null || contract.getZzResultArea().compareTo(BigDecimal.ZERO) <= 0) {
            resultMap = new HashMap<>();
        } else {
            resultMap = overAreaPriceNewService.getOverHouseMoneyMapForMore(contract);
        }
        if (CollectionUtils.isNotEmpty(resultMap)) {
            Map itemMap = Maps.newHashMap();
            for (String str : resultMap.keySet()) {
                itemMap = null;
                itemMap = resultMap.get(str) == null ? Maps.newHashMap() : resultMap.get(str);

                /*存储区间相关面积及金额*/
                if (CollectionUtils.isNotEmpty(itemMap)) {
                    BigDecimal area = BigDecimal.ZERO,price = BigDecimal.ZERO,qjMoney = BigDecimal.ZERO;
                    if (itemMap.get("area") != null) {
                        area = BigDecimalUtils.stringToBigDecimal(itemMap.get("area").toString());
                    }
                    if (itemMap.get("price") != null) {
                        price = BigDecimalUtils.stringToBigDecimal(itemMap.get("price").toString());
                    }
                    if (itemMap.get("money") != null) {
                        qjMoney = BigDecimalUtils.stringToBigDecimal(itemMap.get("money").toString());
                    }
                    if (price.compareTo(new BigDecimal("9100")) == 0) {
                        contract.setTwoQjArea(area);
                        contract.setTwoQjMoney(qjMoney);
                    } else if (price.compareTo(new BigDecimal("3800")) == 0) {
                        contract.setOneQjArea(area);
                        contract.setOneQjMoney(qjMoney);
                    }
                    contractService.save(contract);
                }
            }
        }
    }

    /**
     * 计算车位数量、面积、价格
     *
     * @param contract
     * @return
     */
    private static Contract calCarLotMoney(Contract contract) {
        List<CarLot> carLotList = carLotService.getCarLotListByContractId(contract.getId());
        Integer carLotNum = 0;  //车位数量
        BigDecimal carLotArea = BigDecimal.ZERO;   //车位面积
        BigDecimal carLotMoney = BigDecimal.ZERO;  //车位价格
        if (CollectionUtils.isNotEmpty(carLotList)) {
            carLotNum = 0;
            for (CarLot carLot : carLotList) {
                //车位最终需补交金额计算
                BigDecimal zzXjnPrice = BigDecimal.ZERO;//最终需缴纳金额
                if (carLot.getSfHg() == 2) { //面积换购 优惠20%
                    zzXjnPrice = BigDecimalUtils.getBigAndBigMul(carLot.getZhXbPrice(),new BigDecimal("0.80"));
                } else if (carLot.getSfHg() == 1) {//正常购买 优惠20%
                    zzXjnPrice = BigDecimalUtils.getBigAndBigMul(carLot.getGmXbPrice(),new BigDecimal("0.80"));
                } else { //其它则是评估金额
                    zzXjnPrice = carLot.getGmXbPrice();
                }
                carLot.setZzXjnPrice(zzXjnPrice);
                carLotService.save(carLot);
                /*协议相关计算*/
                carLotNum++;
                carLotArea = BigDecimalUtils.getSum(carLotArea, carLot.getBuildArea());
                carLotMoney = BigDecimalUtils.getSum(carLotMoney,zzXjnPrice);//无论置换或购买都存在缴纳金额
            }
        }

        contract.setCarLotArea(carLotArea);
        contract.setCarLotNum(carLotNum);
        contract.setCarLotMoney(carLotMoney.negate());   //（为负数：被征收人应缴纳金额）

        //现房车位
        List<CarLot> carLotXianFangList = carLotService.getCarLotListByContractIdAndHouseNature(contract.getId(), 1);
        BigDecimal carLotXianFangArea = BigDecimal.ZERO;//现房车位面积
        BigDecimal carLotXianFangPrice = BigDecimal.ZERO;//现房车位金额【购买时】
        BigDecimal carLotXianFangZhArea = BigDecimal.ZERO;//现房车位换购【所需面积】
        if (CollectionUtils.isNotEmpty(carLotXianFangList)) {//现房车位
            for (CarLot carLot : carLotXianFangList) {
                carLotXianFangArea = BigDecimalUtils.getSum(carLotXianFangArea, carLot.getBuildArea());
                if (carLot.getSfHg() == 1) {//正常购买时计算多需金额
                    carLotXianFangPrice = BigDecimalUtils.getSum(carLotXianFangPrice, BigDecimalUtils.getNegateBig(carLot.getPrice()));
                } else if (carLot.getSfHg() == 2) {//面积换购时仅需要计算面积
                    carLotXianFangZhArea = BigDecimalUtils.getSum(carLotXianFangZhArea,carLotService.carLotZhArea(carLot));
                }
            }
        }
        contract.setCarLotXianFangArea(carLotXianFangArea);
        contract.setCarLotXianFangMoney(carLotXianFangPrice);
        contract.setCarLotXianFangZhArea(carLotXianFangZhArea);//现房换后所需面积
        //期房车位
        List<CarLot> carLotQiFangList = carLotService.getCarLotListByContractIdAndHouseNature(contract.getId(), 2);
        BigDecimal carLotQiFangArea = BigDecimal.ZERO;//期房车位面积
        BigDecimal carLotQiFangPrice = BigDecimal.ZERO;//期房车位金额
        BigDecimal carLotQiFangZhArea = BigDecimal.ZERO;//期房车位换购【所需面积】
        if (CollectionUtils.isNotEmpty(carLotQiFangList)) {//期房车位
            for (CarLot carLot : carLotQiFangList) {
                carLotQiFangArea = BigDecimalUtils.getSum(carLotQiFangArea, carLot.getBuildArea());
                if (carLot.getSfHg() == 1) {//正常购买时计算多需金额
                    carLotQiFangPrice = BigDecimalUtils.getSum(carLotQiFangPrice, BigDecimalUtils.getNegateBig(carLot.getPrice()));
                } else if (carLot.getSfHg() == 2) {//面积换购时仅需要计算面积
                    carLotQiFangZhArea = BigDecimalUtils.getSum(carLotQiFangZhArea,carLotService.carLotZhArea(carLot));
                }
            }
        }
        contract.setCarLotQiFangArea(carLotQiFangArea);
        contract.setCarLotQiFangMoney(carLotQiFangPrice);
        contract.setCarLotQiFangZhArea(carLotQiFangZhArea);//期房换购所需面积
        contract.setCarLotTotalZhArea(BigDecimalUtils.getSum(carLotQiFangZhArea,carLotXianFangZhArea));//置换总需面积
        /*人防车位和非人防车位面积保存,用于计算公维金,非人防车位公维金不需缴纳*/
        BigDecimal carLotRfArea = BigDecimal.ZERO;//人防车位面积
        List<CarLot> carLotRfList = carLotService.getNoRfCarLotListByContractId(contract.getId(), "('4','8','5','9')");
        if (CollectionUtils.isNotEmpty(carLotRfList)) {
            for (CarLot carLot : carLotRfList) {
                carLotRfArea = BigDecimalUtils.getSum(carLotRfArea, carLot.getBuildArea());
            }
        }
        contract.setCarLotRfArea(carLotRfArea);

        BigDecimal carLotNoRfArea = BigDecimal.ZERO;//非人防车位面积
        List<CarLot> carLotNoRfList = carLotService.getNoRfCarLotListByContractId(contract.getId(), "('1','7','2','3','6')");
        if (CollectionUtils.isNotEmpty(carLotNoRfList)) {
            for (CarLot carLot : carLotNoRfList) {
                carLotNoRfArea = BigDecimalUtils.getSum(carLotNoRfArea, carLot.getBuildArea());
            }
        }

        contract.setCatLotNoRfArea(carLotNoRfArea);

        if (contract.getIsJiSuan() != null) {
            if (contract.getIsJiSuan() == 2 || contract.getIsJiSuan() == 3) {
                contract.setZzResultArea(BigDecimal.ZERO);
            }
        }
        return contract;
    }

    /**
     * 计算住宅临时安置补助费
     */
    private static Contract calBzMoney(Contract contract) {
        BigDecimal zzbzMoney = BigDecimal.ZERO, zxbzMoney = BigDecimal.ZERO, bzMoneyTotal = BigDecimal.ZERO;
        //腾空日期，开始选房日期
        //自动计算
        if (contract.getIsDoubleMoney() != null && contract.getIsDoubleMoney() == 0) {
            int betweenMonth = CalculateDate.getDatesForMonth(contract.getTkDate(), contract.getChooseHouseDate());
            //住宅临时安置补助费
            if (betweenMonth > 36) {
                zzbzMoney = BigDecimalUtils.getBigAndBigMul(contract.getZzgdMoney(), new BigDecimal("2")).setScale(0, BigDecimal.ROUND_HALF_UP);   //发两个月的周转费
            } else {
                zzbzMoney = BigDecimalUtils.getNotNull(contract.getZzgdMoney()).setScale(0, BigDecimal.ROUND_HALF_UP);   //发一个月的周转费
            }
        }
        //手动计算
        else {
            //单倍
            if (contract.getIsDoubleMoney() != null && contract.getIsDoubleMoney() == 1) {
                zzbzMoney = BigDecimalUtils.getNotNull(contract.getZzgdMoney()).setScale(0, BigDecimal.ROUND_HALF_UP);   //发一个月的周转费
            }
            //双倍
            else if (contract.getIsDoubleMoney() != null && contract.getIsDoubleMoney() == 2) {
                zzbzMoney = BigDecimalUtils.getBigAndBigMul(contract.getZzgdMoney(), new BigDecimal("2")).setScale(0, BigDecimal.ROUND_HALF_UP);   //发两个月的周转费
            }
        }
        //装修补助费   =  每月应发的装修周转过渡费*3个月
        zxbzMoney = BigDecimalUtils.getBigAndBigMul(contract.getZxgdMoney(), new BigDecimal("3")).setScale(0, BigDecimal.ROUND_HALF_UP);

        bzMoneyTotal = BigDecimalUtils.getSum(zzbzMoney, zxbzMoney);

        contract.setZzbzMoney(zzbzMoney);
        contract.setZxbzMoney(zxbzMoney);
        contract.setBzMoneyTotal(bzMoneyTotal);
        return contract;
    }


    /**
     * 计算住宅专项维修基金
     *
     * @param contract
     * @return
     */
    private static Contract calWxMoney(Contract contract) {
        BigDecimal zzwxMoney = BigDecimal.ZERO, zzwxQiFangMoney = BigDecimal.ZERO, zzwxXianFangMoney = BigDecimal.ZERO,
                ccjwxMoney = BigDecimal.ZERO,
                cwwxMoney = BigDecimal.ZERO, cwwxXianFangMoney = BigDecimal.ZERO, cwwxQiFangMoney = BigDecimal.ZERO,
                dmwxMoney = BigDecimal.ZERO,
                wxMoneyTotal = BigDecimal.ZERO;
        //如果配置参数里住宅有本次缴交比例，则根据每套房的标准*比例累加，
        //若是征收项目id 大于256 即为2024年7月18日后新回迁项目单价皆按单栋最高层计算
        if (contract.getZsProject().getId() > 0) {
            List<House> houseList1 = houseService.getHouseListByContractIdAndHouseNature1(contract.getId());
            List<House> houseList2 = houseService.getHouseListByContractIdAndHouseNature2(contract.getId());
            if (CollectionUtils.isNotEmpty(houseList1)) {//现房公维金金额
                for (House house : houseList1) {
                    BigDecimal gwjPrice = houseService.getGwjPrice(houseService.getMaxFloor(house.getAzProject().getId(),house.getBuildNum()));
                    //公维金单价存入到房源信息中
                    house.setGwjPrice(gwjPrice);
                    house.setGwjMoney(
                            BigDecimalUtils.getBigAndBigMul(
                                    BigDecimalUtils.getBigAndBigMul(house.getBuildArea(),gwjPrice),//计算得出公维金单价
                                    BigDecimal.ONE//正常缴纳比例
                            ).setScale(2, BigDecimal.ROUND_HALF_UP)
                    );
                    houseService.save(house);

                    zzwxXianFangMoney = BigDecimalUtils.getSum(
                            zzwxXianFangMoney,
                            BigDecimalUtils.getBigAndBigMul(
                                    BigDecimalUtils.getBigAndBigMul(house.getBuildArea(),gwjPrice),//计算得出公维金单价
                                    BigDecimal.ONE//正常缴纳比例
                            )
                    ).setScale(2, BigDecimal.ROUND_HALF_UP);
                }
            }
            zzwxXianFangMoney = zzwxXianFangMoney.negate();

            if (CollectionUtils.isNotEmpty(houseList2)) {//期房公维金金额
                for (House house : houseList2) {
                    BigDecimal gwjPrice = houseService.getGwjPrice(houseService.getMaxFloor(house.getAzProject().getId(),house.getBuildNum()));
                    //公维金单价存入到房源信息中
                    house.setGwjPrice(gwjPrice);
                    house.setGwjMoney(
                            BigDecimalUtils.getBigAndBigMul(
                                    BigDecimalUtils.getBigAndBigMul(house.getBuildArea(),gwjPrice),//计算得出公维金单价
                                    contract.getParameter().getGwjHouseNowBl()
                            ).setScale(2, BigDecimal.ROUND_HALF_UP)
                    );
                    houseService.save(house);
                    zzwxQiFangMoney = BigDecimalUtils.getSum(
                            zzwxQiFangMoney,
                            BigDecimalUtils.getBigAndBigMul(
                                    BigDecimalUtils.getBigAndBigMul(house.getBuildArea(),gwjPrice),//计算得出公维金单价
                                    contract.getParameter().getGwjHouseNowBl()
                            )
                    ).setScale(2, BigDecimal.ROUND_HALF_UP);
                }
            }
            zzwxQiFangMoney = zzwxQiFangMoney.negate();
            //住宅公维金计算
            zzwxMoney = BigDecimalUtils.getSum(zzwxQiFangMoney, zzwxXianFangMoney).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        //储藏间
        if (contract.getAzType().contains("商业")) {
            ccjwxMoney = BigDecimalUtils.getBigAndBigMul(contract.getStorageRoomArea(), new BigDecimal("50")).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
        } else {
            ccjwxMoney = BigDecimalUtils.getBigAndBigMul(contract.getStorageRoomArea(), contract.getParameter().getCcjbcwxPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
        }

        //店面维修金金额计算
        List<ShopHouse> shopHouseList = shopHouseService.getShopHouseListByContractId(contract.getId());
        if (CollectionUtils.isNotEmpty(shopHouseList)) {
            for (ShopHouse shopHouse : shopHouseList) {
                dmwxMoney = BigDecimalUtils.getSum(
                        dmwxMoney,
                        BigDecimalUtils.getBigAndBigMul(shopHouse.getBuildArea(),shopHouse.getGwjPrice()).setScale(2, BigDecimal.ROUND_HALF_UP)
                );
                //将公维金保存到对应的店面中
                shopHouse.setGwjMoney(BigDecimalUtils.getBigAndBigMul(shopHouse.getBuildArea(),shopHouse.getGwjPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate());
                shopHouseService.save(shopHouse);
            }
        }
        dmwxMoney = dmwxMoney.setScale(2, BigDecimal.ROUND_HALF_UP).negate();
        //车位、期房、现房、合计
        if (contract.getAzType().contains("商业")) {
            cwwxXianFangMoney = BigDecimalUtils.getBigAndBigMul(contract.getCarLotXianFangArea(), new BigDecimal("35")).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
            cwwxQiFangMoney = BigDecimalUtils.getBigAndBigMul(contract.getCarLotQiFangArea(), new BigDecimal("35")).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
            cwwxMoney = BigDecimalUtils.getBigAndBigMul(contract.getCatLotNoRfArea(), new BigDecimal("35")).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
        } else {
            cwwxXianFangMoney = BigDecimalUtils.getBigAndBigMul(contract.getCarLotXianFangArea(), contract.getParameter().getCwbcwxPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
            cwwxQiFangMoney = BigDecimalUtils.getBigAndBigMul(contract.getCarLotQiFangArea(), contract.getParameter().getCwbcwxPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
            cwwxMoney = BigDecimalUtils.getBigAndBigMul(contract.getCatLotNoRfArea(), contract.getParameter().getCwbcwxPrice()).setScale(2, BigDecimal.ROUND_HALF_UP).negate();
        }


        //总合计
        wxMoneyTotal = BigDecimalUtils.getSum(zzwxMoney, ccjwxMoney, cwwxMoney,dmwxMoney);
        contract.setZzwxQiFangMoney(zzwxQiFangMoney);
        contract.setZzwxXianFangMoney(zzwxXianFangMoney);
        contract.setZzwxMoney(zzwxMoney);
        contract.setCcjwxMoney(ccjwxMoney);
        contract.setCwwxXianFangMoney(cwwxXianFangMoney);
        contract.setCwwxQiFangMoney(cwwxQiFangMoney);
        contract.setCwwxMoney(cwwxMoney);
        contract.setDmwxMoney(dmwxMoney);
        contract.setWxMoneyTotal(wxMoneyTotal);
        return contract;
    }

    /**
     * 安置协议编号后缀添加
     * @param contract
     * @return
     */
    private static Contract contractCodeZzAddCal(Contract contract) {
        List<House> houseList = houseService.getHouseListByContractId(contract.getId());
        List<CarLot> carLotList = carLotService.getCarLotListByContractId(contract.getId());
        List<ShopHouse> shopHouseList = shopHouseService.getShopHouseListByContractId(contract.getId());
        if (CollectionUtils.isNotEmpty(houseList)) {
            int count =  0;
            for (House house : houseList) {
                count++;
                StringBuffer code = new StringBuffer("");
                code.append("("+ houseList.size() +")-");
                code.append(count);
                house.setContractCodeZzAddCal(code.toString());
                houseService.save(house);
            }
        }

        if (CollectionUtils.isNotEmpty(carLotList)) {
            int count =  0;
            for (CarLot carLot : carLotList) {
                count++;
                StringBuffer code = new StringBuffer("");
                code.append("("+ carLotList.size() +")-");
                code.append(count);
                carLot.setContractCodeCarCarAddCal(code.toString());
                carLotService.save(carLot);
            }
        }

        if (CollectionUtils.isNotEmpty(shopHouseList)) {
            int count =  0;
            for (ShopHouse shopHouse : shopHouseList) {
                count++;
                StringBuffer code = new StringBuffer("");
                code.append("("+ shopHouseList.size() +")-");
                code.append(count);
                shopHouse.setContractCodeShopAddCal(code.toString());
                shopHouseService.save(shopHouse);
            }
        }
        return contract;
    }

    /**
     * 计算其它相关费用以及汇总费用
     *
     * @param contract
     * @return
     */
    private static Contract calOtherMoney(Contract contract) {
        BigDecimal houseOneMoney = BigDecimal.ZERO;//财务表（1）合计金额
        BigDecimal finalMoney = BigDecimal.ZERO;
        BigDecimal houseFinalMoney = BigDecimal.ZERO;
        BigDecimal carLotFinalMoney = BigDecimal.ZERO;
        BigDecimal storageRoomFinalMoney = BigDecimal.ZERO;
        BigDecimal wxMoneyTotal = BigDecimal.ZERO;//维修金总金额

        BigDecimal kjYjMoney = BigDecimal.ZERO;//开间≤3.3米应缴款
        BigDecimal kqjYjMoney = BigDecimal.ZERO;//跨街区安置应缴款

        kjYjMoney = contract.getParameter() == null ? kjYjMoney : contract.getParameter().getKjYjMoney();
        kqjYjMoney = contract.getParameter() == null ? kqjYjMoney : contract.getParameter().getKqjYjMoney();

        /*财务结算表第一张金额*/
        houseOneMoney = BigDecimalUtils.getSum(
                contract.getZzgdMoney(),//装修过渡费
                contract.getHouseMoney(),//房屋购房款
                contract.getZxgdMoney(),//停产停业补助
                contract.getResultMoney(),//征迁应缴金额
                contract.getCarLotMoney(),//车位需缴购房款
                kjYjMoney,//开间≤3.3米应缴款
                kqjYjMoney//跨街区安置应缴款
        ).setScale(2, BigDecimal.ROUND_HALF_UP);
        /*财务结算表第一张金额*/
        wxMoneyTotal = BigDecimalUtils.getSum(
                contract.getZzwxMoney(),//住宅维修金额
                contract.getCwwxMoney(),//车位维修金
                contract.getDmwxMoney()//店面维修金
        );


        //前面几项累计 - 应缴交金额
        finalMoney = BigDecimalUtils.getSum(
                contract.getResultMoney(),   //应缴交金额
                contract.getHouseMoney(),   //购房款
                contract.getStorageRoomMoney(),   //购买储物间钱款
                contract.getCarLotMoney(),   //购买车位钱款
                contract.getBzMoneyTotal(),   //过渡补助金额
                contract.getWxMoneyTotal(),   //专项维修基金
                contract.getOtherMoney(),   //其它金额
                contract.getKkgHouseMoney()   //可扩改面积应缴款
        ).setScale(2, BigDecimal.ROUND_HALF_UP);
        houseFinalMoney = BigDecimalUtils.getSum(
                contract.getResultMoney(),   //应缴交金额
                contract.getHouseMoney(),   //购房款
                contract.getBzMoneyTotal(),   //过渡补助金额
                contract.getZzwxMoney(),   //住宅维修基金
                contract.getOtherMoney(),  //其它金额
                contract.getKkgHouseMoney() //可扩改面积应缴款
        ).setScale(2, BigDecimal.ROUND_HALF_UP);
        carLotFinalMoney = BigDecimalUtils.getSum(
                contract.getCwwxMoney(),
                contract.getCarLotMoney()
        ).setScale(2, BigDecimal.ROUND_HALF_UP);
        storageRoomFinalMoney = BigDecimalUtils.getSum(
                contract.getCcjwxMoney(),
                contract.getStorageRoomMoney()
        ).setScale(2, BigDecimal.ROUND_HALF_UP);
        contract.setHouseOneMoney(houseOneMoney);
        contract.setFinalMoney(finalMoney);
        contract.setHouseFinalMoney(houseFinalMoney);
        contract.setCarLotFinalMoney(carLotFinalMoney);
        contract.setStorageRoomFinalMoney(storageRoomFinalMoney);
        contract.setWxMoneyTotal(wxMoneyTotal);
        return contract;
    }


    /**
     * 计算选房过后剩余产权调换和照顾购买面积
     *
     * @param contract
     * @return
     */
    private static Contract calSyArea(Contract contract) {
        BigDecimal sycqdhArea = BigDecimal.ZERO;
        BigDecimal syzggmArea = BigDecimal.ZERO;
        BigDecimal allChooseArea = contract.getChooseHouseAreaTotal();
        if (contract.getBuyStorageRoomType() != null && contract.getBuyStorageRoomType() == 1) {
            allChooseArea = BigDecimalUtils.getSum(contract.getChooseHouseAreaTotal(),
                    BigDecimalUtils.getBigAndBigDiv(contract.getStorageRoomArea(), contract.getParameter().getCwjBl(), 2));
        }
        if (contract.getPropertyChangeArea().compareTo(allChooseArea) >= 0) {
            sycqdhArea = BigDecimalUtils.getBigAndBigSub(contract.getPropertyChangeArea(), allChooseArea);
            syzggmArea = BigDecimalUtils.getSum(contract.getCareBuyArea1(), contract.getCareBuyArea2(), contract.getCareBuyArea3(), contract.getCareBuyArea4(),
                    contract.getCareBuyArea5(), contract.getCareBuyArea6(), contract.getCareBuyArea7(), contract.getCareBuyArea8());
        } else if (contract.getPropertyChangeArea().compareTo(allChooseArea) < 0) {
            syzggmArea = BigDecimalUtils.getBigAndBigSub(contract.getLimitHouseAreaTotal(), allChooseArea);
        }
        contract.setSycqdhArea(sycqdhArea.compareTo(new BigDecimal("0")) >= 0 ? sycqdhArea : new BigDecimal("0"));
        contract.setSyzggmArea(syzggmArea.compareTo(new BigDecimal("0")) >= 0 ? syzggmArea : new BigDecimal("0"));
        return contract;
    }

    /**
     * 计算房源的面积、数量
     *
     * @param contract
     * @return
     */
    private static Contract calKkgArea(Contract contract) {

        BigDecimal kkgHouseArea = BigDecimal.ZERO, kkgHouseMoney = BigDecimal.ZERO;
        List<House> houseList = houseService.getHouseListByContractId(contract.getId());

        if (CollectionUtils.isNotEmpty(houseList)) {
            for (House house : houseList) {
                kkgHouseArea = BigDecimalUtils.getSum(kkgHouseArea, house.getKkgArea());
            }
            kkgHouseMoney = BigDecimalUtils.getBigAndBigMul(kkgHouseArea, contract.getParameter().getKkgPrice()).negate();
        }
        contract.setKkgHouseArea(kkgHouseArea);
        contract.setKkgHouseMoney(kkgHouseMoney);
        return contract;
    }

    /**
     * 计算协议的的契税、印花税
     *
     * @param contract
     * @return
     */
    private static Contract calTaxMoney(Contract contract) {
        calTaxHouseMoney(contract);
        calTaxStorageMoney(contract);
        calTaxCarLotMoney(contract);
        //房源总应缴契税---车位储物间总应缴契税---总应缴契税
        BigDecimal taxHouseMoney = BigDecimal.ZERO, taxCarAndStorageMoney = BigDecimal.ZERO, taxMoney = BigDecimal.ZERO;
        //房源总应缴印花税---车位储物间总应缴印花税---总应缴印花税
        BigDecimal taxHouseYhsMoney = BigDecimal.ZERO, taxCarAndStorageYhsMoney = BigDecimal.ZERO, taxYhsMoney = BigDecimal.ZERO;
        List<House> houseList = houseService.getHouseListNoSpByContractId(contract.getId());
        List<StorageRoom> storageRoomList = storageRoomService.getStorageRoomListByContractId(contract.getId());
        List<CarLot> carLotList = carLotService.getCarLotListByContractId(contract.getId());
        for (House house : houseList) {
            taxHouseMoney = BigDecimalUtils.getSum(taxHouseMoney, house.getTaxMoney());
            taxHouseYhsMoney = BigDecimalUtils.getSum(taxHouseYhsMoney, house.getTaxYhsMoney());
        }
        for (StorageRoom storageRoom : storageRoomList) {
            taxCarAndStorageMoney = BigDecimalUtils.getSum(taxCarAndStorageMoney, storageRoom.getTaxMoney());
            taxCarAndStorageYhsMoney = BigDecimalUtils.getSum(taxCarAndStorageYhsMoney, storageRoom.getTaxYhsMoney());
        }
        for (CarLot carLot : carLotList) {
            taxCarAndStorageMoney = BigDecimalUtils.getSum(taxCarAndStorageMoney, carLot.getTaxMoney());
            taxCarAndStorageYhsMoney = BigDecimalUtils.getSum(taxCarAndStorageYhsMoney, carLot.getTaxYhsMoney());
        }
        taxMoney = BigDecimalUtils.getSum(taxHouseMoney, taxCarAndStorageMoney);
        taxYhsMoney = BigDecimalUtils.getSum(taxHouseYhsMoney, taxCarAndStorageYhsMoney);

        contract.setTaxHouseMoney(taxHouseMoney);
        contract.setTaxCarAndStorageMoney(taxCarAndStorageMoney);
        contract.setTaxMoney(taxMoney);
        contract.setTaxHouseYhsMoney(taxHouseYhsMoney);
        contract.setTaxCarAndStorageYhsMoney(taxCarAndStorageYhsMoney);
        contract.setTaxYhsMoney(taxYhsMoney);
        contractService.save(contract);
        return contract;
    }

    /**
     * 计算房源的安置房金额、拆迁面积、拆迁补偿金额、契税、印花税
     *
     * @param contract
     * @return
     */
    private static Contract calTaxHouseMoney(Contract contract) {
        BigDecimal taxAzArea = BigDecimal.ZERO, taxAzAreaMoney = BigDecimal.ZERO, taxHouseMoney = BigDecimal.ZERO, taxMoney = BigDecimal.ZERO;
        BigDecimal price = BigDecimal.ZERO, area = BigDecimal.ZERO;
        BigDecimal allTaxAzArea = BigDecimal.ZERO;
        List<House> houseList = houseService.getHouseListNoSpByContractId(contract.getId());
        List<Map> mapList = AreaAndPriceUtils.getAreaAndPriceList(contract);
        BigDecimal noSpfArea = houseService.getNoSpfArea(contract.getId());

        //累计扣除面积
        if (CollectionUtils.isNotEmpty(houseList)) {
            for (House house : houseList) {
                taxAzArea = BigDecimal.ZERO;
                taxAzAreaMoney = BigDecimal.ZERO;
                taxHouseMoney = BigDecimal.ZERO;
                for (Map map : mapList) {
                    area = map.get("area") == null ? BigDecimal.ZERO : BigDecimalUtils.stringToBigDecimal(map.get("area").toString());
                    price = map.get("price") == null ? BigDecimal.ZERO : BigDecimalUtils.stringToBigDecimal(map.get("price").toString());
                    if (map.get("project").equals("产权调换面积")) {
                        //拆迁面积即使用产权调换面积taxAzArea
                        if (houseList.size() - 1 == houseList.indexOf(house)) {
                            taxAzArea = BigDecimalUtils.getBigAndBigSub(contract.getPropertyChangeArea(),contract.getKcPropertyChangeArea()).compareTo(noSpfArea) > 0 ?
                                    house.getBuildArea() :
                                    BigDecimalUtils.getBigAndBigSub(BigDecimalUtils.getBigAndBigSub(contract.getPropertyChangeArea(),contract.getKcPropertyChangeArea()), allTaxAzArea);
                        } else {
                            taxAzArea = BigDecimalUtils.getBigAndBigMul(house.getBuildArea(), BigDecimalUtils.getBigAndBigDiv(area, noSpfArea, 12)).setScale(11, BigDecimal.ROUND_HALF_UP);
                            allTaxAzArea = BigDecimalUtils.getSum(allTaxAzArea, taxAzArea);
                        }
                        //拆迁补偿金额，即使用产权调换部分taxAzArea*price
                        taxAzAreaMoney = BigDecimalUtils.getBigAndBigMul(taxAzArea, price);
                        house.setTaxAzArea(taxAzArea);
                        house.setTaxAzAreaMoney(taxAzAreaMoney);
                    }
                    //该部分比例----当前区间面积/总选房面积
                    //房产总价值----房源面积*当前使用该部分面积比例*单价
                    taxHouseMoney = BigDecimalUtils.getSum(
                            taxHouseMoney,
                            BigDecimalUtils.getBigAndBigMul(
                                BigDecimalUtils.getBigAndBigMul(
                                        house.getBuildArea(),
                                        BigDecimalUtils.getBigAndBigDiv(area, noSpfArea, 12)).setScale(11, BigDecimal.ROUND_HALF_UP), price));

                    //契税---（房产总价值-拆迁面积）/1.05*0.03
                    taxMoney = BigDecimalUtils.getBigAndBigMul(BigDecimalUtils.getBigAndBigDiv(BigDecimalUtils.getBigAndBigSub(taxHouseMoney, taxAzAreaMoney), contract.getSfJs(), 10), new BigDecimal("0.03")).setScale(11, BigDecimal.ROUND_HALF_UP);

                    house.setTaxHouseMoney(taxHouseMoney);
                    house.setTaxMoney(taxMoney);
                    house.setTaxYhsMoney(BigDecimal.ZERO);
                    houseService.save(house);
                }
            }
        }
        return contract;
    }

    /**
     * 计算储物间的契税、印花税
     *
     * @param contract
     * @return
     */
    private static Contract calTaxStorageMoney(Contract contract) {
        BigDecimal storageMoney = BigDecimal.ZERO, taxStorageMoney = BigDecimal.ZERO, taxStorageYhsMoney = BigDecimal.ZERO;
        List<StorageRoom> storageRoomList = storageRoomService.getStorageRoomListByContractId(contract.getId());

        if (CollectionUtils.isNotEmpty(storageRoomList)) {
            for (StorageRoom storageRoom : storageRoomList) {
                //储物间房产价值----建筑面积*2000（默认使用购买）
                storageMoney = BigDecimalUtils.getBigAndBigMul(storageRoom.getBuildArea(), new BigDecimal("2000"));
                //储物间契税----储物间房产价值storageMoney/1.05*0.03
                taxStorageMoney = BigDecimalUtils.getBigAndBigMul(BigDecimalUtils.getBigAndBigDiv(storageMoney, contract.getSfJs(), 6), new BigDecimal("0.03"));
                //储物间印花税---储物间房产价值storageMoney*0.00025
                taxStorageYhsMoney = BigDecimalUtils.getBigAndBigMul(storageMoney, new BigDecimal("0.00025"));
                storageRoom.setTaxStorageMoney(storageMoney);
                storageRoom.setTaxMoney(taxStorageMoney);
                storageRoom.setTaxYhsMoney(taxStorageYhsMoney);
                storageRoomService.save(storageRoom);
            }
        }
        return contract;
    }

    /**
     * 计算车位的契税、印花税
     *
     * @param contract
     * @return
     */
    private static Contract calTaxCarLotMoney(Contract contract) {
        List<CarLot> carLotList = carLotService.getCarLotListByContractId(contract.getId());
        BigDecimal taxCarLotMoney = BigDecimal.ZERO, taxCarLotYhsMoney = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(carLotList)) {
            for (CarLot carLot : carLotList) {
                //契税----车位价格price/1.05*0.03
                taxCarLotMoney = BigDecimalUtils.getBigAndBigMul(BigDecimalUtils.getBigAndBigDiv(carLot.getPrice(), contract.getSfJs(), 6), new BigDecimal("0.03"));
                //印花税---车位价格price*0.00025(2019-1-1后选房)
                taxCarLotYhsMoney = BigDecimalUtils.getBigAndBigMul(carLot.getPrice(), new BigDecimal("0.00025"));
                carLot.setTaxMoney(taxCarLotMoney);
                carLot.setTaxYhsMoney(taxCarLotYhsMoney);
                carLotService.save(carLot);
            }
        }
        return contract;
    }

    /**
     * 计算合并面积
     * @param contract
     * @return
     */
    private static Contract calAdjustArea(Contract contract) {
        List<AdjustArea> adjustAreaList = adjustAreaService.getAdjustAreaListByContractId(contract.getId());
        BigDecimal adjustArea = BigDecimal.ZERO;//合并的产权面积
        BigDecimal adjustZgArea = BigDecimal.ZERO;//合并的照顾购买面积
        if (CollectionUtils.isNotEmpty(adjustAreaList)) {
            for (AdjustArea adjustAreaItem : adjustAreaList) {
                if (adjustAreaItem.getType().equals("产权调换")) {
                    adjustArea = BigDecimalUtils.getSum(adjustArea,adjustAreaItem.getAdjustArea());
                } else if (adjustAreaItem.getType().equals("照顾购买面积")) {
                    adjustZgArea = BigDecimalUtils.getSum(adjustZgArea,adjustAreaItem.getAdjustArea());
                }
            }
        }
        contract.setAdjustArea(adjustArea);
        contract.setAdjustZgArea(adjustZgArea);
        return contract;
    }

}
